package View;

import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JTextArea;

import java.awt.Point;
import java.awt.Rectangle;

import javax.swing.JFileChooser;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;

import fileManager.ReadercoSnd;
import fileManager.WritercoSnd;

import programManager.Compiler;


import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.File;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.awt.Color;
import javax.swing.JToggleButton;

import midiPlayer.MIDIPlayer;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;

public class MainWindow extends JFrame {

	/**
	 * Graphic Components
	 */
	
	private static final long serialVersionUID = 1L;
	private JPanel jContentPane = null;
	private JMenuBar jJMenuBar = null;
	private JMenu jMenu = null;
	private JMenuItem jMenuItem1 = null;
	private JMenuItem jMenuItem2 = null;
	private JButton jButton = null;
	private JScrollPane jScrollPane = null;
	private JTextArea jTextArea = null;
	private JMenu jMenu2 = null;
	private JMenuItem jMenuItem = null;
	private JMenuItem jMenuItem3 = null;
	private JFileChooser fc = null;
	public  JTextArea jTextArea1 = null;
	private JScrollPane jScrollPane1 = null;
	private MIDIPlayer mp = null;

	/**
	 * Read Console Variables
	 */
    PipedInputStream piOut;  //  @jve:decl-index=0:
    PipedInputStream piErr;  //  @jve:decl-index=0:
    PipedOutputStream poOut;
    PipedOutputStream poErr;  //  @jve:decl-index=0:
	private JToggleButton jToggleButton = null;
	private JPanel jPanel = null;
	
	
	/**
	 * This method initializes jJMenuBar	
	 * 	
	 * @return javax.swing.JMenuBar	
	 */
	private JMenuBar getJJMenuBar() {
		if (jJMenuBar == null) {
			jJMenuBar = new JMenuBar();
			jJMenuBar.add(getJMenu());
			jJMenuBar.add(getJMenu2());
		}
		return jJMenuBar;
	}

	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */
	private JMenu getJMenu() {
		if (jMenu == null) {
			jMenu = new JMenu();
			jMenu.setText("File");
			jMenu.add(getJMenuItem1());
			jMenu.add(getJMenuItem2());
			jMenu.add(getJMenuItem3());
		}
		return jMenu;
	}

	/**
	 * This method initializes jMenuItem1	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	private JMenuItem getJMenuItem1() {
		if (jMenuItem1 == null) {
			jMenuItem1 = new JMenuItem();
			jMenuItem1.setText("New");
			jMenuItem1.addActionListener(new  ActionListener() {
				
				@Override
				public void actionPerformed(ActionEvent e) {
					// TODO Auto-generated method stub
					int ans = JOptionPane.NO_OPTION;
					if(!jTextArea.getText().equals(""))
						ans = JOptionPane.showConfirmDialog(null, "Do you want to save?", "Action", JOptionPane.YES_NO_OPTION);
					
					if(ans == JOptionPane.YES_OPTION){

						fc = new JFileChooser();
						int returnVal = fc.showSaveDialog(new JFileChooser());
						fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
						
						if(returnVal == JFileChooser.APPROVE_OPTION){
							new WritercoSnd().write(fc.getSelectedFile().getName(), jTextArea.getText(), fc.getSelectedFile().getPath().substring(0,fc.getSelectedFile().getPath().length()-fc.getSelectedFile().getName().length()));
						}
					}
					
						
					jTextArea.setText("");
					jTextArea1.setText("");
					
				}
			});
		}
		return jMenuItem1;
	}

	/**
	 * This method initializes jMenuItem2	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	private JMenuItem getJMenuItem2() {
		if (jMenuItem2 == null) {
			jMenuItem2 = new JMenuItem();
			jMenuItem2.setText("Open");
			jMenuItem2.addActionListener(new ActionListener() {
				
				@Override
				public void actionPerformed(ActionEvent e) {
					// TODO Auto-generated method stub
					fc = new JFileChooser();
					fc.setFileFilter(new coSndFilter());
					fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
					
					int returnVal = fc.showOpenDialog(new JFileChooser());
					
					if(returnVal == JFileChooser.APPROVE_OPTION){
						
						String prog; 
						
						if((prog = new ReadercoSnd().read(fc.getSelectedFile())) != null){
							jTextArea.setText(prog);
						}else
							JOptionPane.showMessageDialog(null, "No se pudo leer el archivo", "Error", JOptionPane.ERROR_MESSAGE);
					
					}
				}
			});
		}
		return jMenuItem2;
	}
	
	/**
	 * This method initializes jMenuItem3	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	private JMenuItem getJMenuItem3() {
		if (jMenuItem3 == null) {
			jMenuItem3 = new JMenuItem();
			jMenuItem3.setText("Save");
			jMenuItem3.addActionListener(new ActionListener() {
				
				@Override
				public void actionPerformed(ActionEvent e) {
					// TODO Auto-generated method stub
					
					fc = new JFileChooser();
					int returnVal = fc.showSaveDialog(new JFileChooser());
					fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
					
					if(returnVal == JFileChooser.APPROVE_OPTION)
						new WritercoSnd().write(fc.getSelectedFile().getName(), jTextArea.getText(), fc.getSelectedFile().getPath().substring(0,fc.getSelectedFile().getPath().length()-fc.getSelectedFile().getName().length()));
				}
			});
		}
		return jMenuItem3;
	}

	/**
	 * This method initializes jButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJButton() {
		if (jButton == null) {
			jButton = new JButton();
			jButton.setBounds(new Rectangle(633, 434, 116, 36));
			jButton.setText("Generar");
			jButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
                                        Compiler.compile(jTextArea.getText());
				}
			});
		}
		return jButton;
	}

	/**
	 * This method initializes jScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getJScrollPane() {
		if (jScrollPane == null) {
			jScrollPane = new JScrollPane();
			jScrollPane.setBounds(new Rectangle(54, 24, 705, 189));
			//jScrollPane.setFont(new Font("Lucida Bright", Font.BOLD, 14));
			jScrollPane.setViewportView(getJTextArea());
			
		}
		return jScrollPane;
	}

	/**
	 * This method initializes jTextArea	
	 * 	
	 * @return javax.swing.JTextArea	
	 */
	private JTextArea getJTextArea() {
		if (jTextArea == null) {
			jTextArea = new JTextArea();
		}
		return jTextArea;
	}

	/**
	 * This method initializes jMenu2	
	 * 	
	 * @return javax.swing.JMenu	
	 */
	private JMenu getJMenu2() {
		if (jMenu2 == null) {
			jMenu2 = new JMenu();
			jMenu2.setText("Help");
			jMenu2.add(getJMenuItem());
			
		}
		return jMenu2;
	}

	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	private JMenuItem getJMenuItem() {
		if (jMenuItem == null) {
			jMenuItem = new JMenuItem();
			jMenuItem.setText("About");
			jMenuItem.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					String about = 	"         Code Sound v1.0 \n\n\n\n"+
									"This program was made by:\n\n" +
									"    Sergio Alenadro Gonzalez Espinosa\n" +
									"    Alfonso Rebollar Avalos\n" +
									"    Luis Isaias Vaca Vaca\n" +
									"";
					JOptionPane.showMessageDialog(null,	about, "Code Sound v1.0",JOptionPane.INFORMATION_MESSAGE);
					/*for (int i = 0; i < 20; i++) {
						System.out.println("Hola");
					}*/
					
				}
			});
			
		}
		return jMenuItem;
	}

	/**
	 * This is the default constructor
	 * @throws IOException 
	 */
	public MainWindow() throws IOException {
		super();
		initialize();
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		setLocationRelativeTo(null);
		setResizable(false);
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 * @throws IOException 
	 */
	private void initialize() throws IOException {
		this.setSize(816, 540);
		this.setJMenuBar(getJJMenuBar());
		this.setContentPane(getJContentPane());
		this.setTitle("Code Sound");
			
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 * @throws IOException 
	 */
	private JPanel getJContentPane() throws IOException {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			mp = new MIDIPlayer(this);
			jContentPane.setLayout(null);
			jContentPane.add(getJButton(), null);
			jContentPane.add(getJScrollPane(), null);
			jContentPane.add(getJToggleButton(), null);
			jContentPane.add(getJPanel(), null);
		}
		return jContentPane;
	}

	/**
	 * This method initializes jScrollPane1	
	 * 	
	 * @return javax.swing.JScrollPane	
	 * @throws IOException 
	 */
	private JScrollPane getJScrollPane1() throws IOException {
		if (jScrollPane1 == null) {
			jScrollPane1 = new JScrollPane();
			jScrollPane1.setBorder(null);
			jScrollPane1.setViewportView(getConsoleTArea());
			jScrollPane1.setEnabled(false);
		}
		return jScrollPane1;
	}

	private JTextArea getConsoleTArea() throws IOException {
		// TODO Auto-generated method stub
		if(jTextArea1 == null){
			jTextArea1 = new JTextArea();
		        
		        // Add a scrolling text area
		        //jTextArea1.setFont(new Font("Rekha", Font.PLAIN, 14));
		        jTextArea1.setBackground(Color.black);
		        jTextArea1.setForeground(Color.white);
		        jTextArea1.setEditable(false);
		        jTextArea1.setColumns(15);
		        jTextArea1.setRows(40);
		        
			// Set up System.out
		        piOut = new PipedInputStream();
		        poOut = new PipedOutputStream(piOut);
		        System.setOut(new PrintStream(poOut, true));

		        // Set up System.err
		        piErr = new PipedInputStream();
		        poErr = new PipedOutputStream(piErr);
		        System.setErr(new PrintStream(poErr, true));
		        
		        // Create reader threads
		        new ReaderThread(piOut).start();
		        new ReaderThread(piErr).start();
		}
		return jTextArea1;
	}
	
	/**
	 * 
	 * ReaderThread
	 * 
	 * Read all console messages out, err.
	 *
	 */

	class ReaderThread extends Thread {
	    PipedInputStream pi;
	    ReaderThread(PipedInputStream pi) {
	        this.pi = pi;
	    }

	    public void run() {
	        final byte[] buf = new byte[1024];
	        try {
	            while (true) {
                        final int len = pi.read(buf);
	                if (len == -1) {
	                    break;
	                }
	                SwingUtilities.invokeLater(new Runnable() {
	                    public void run() {
	                    	jTextArea1.append(new String(buf, 0, len));

	                        // Make sure the last line is always visible
	                        jTextArea1.setCaretPosition(jTextArea1.getDocument().getLength());

	                        // Keep the text area down to a certain character size
	                        int idealSize = 1000;
	                        int maxExcess = 500;
	                        int excess = jTextArea1.getDocument().getLength() - idealSize;
	                        if (excess >= maxExcess) {
	                            jTextArea1.replaceRange("", 0, excess);
	                        }
	                    }
	                });
	            }
	        } catch (IOException e) {
	        }
	    }
	}

	/**
	 * This method initializes jToggleButton	
	 * 	
	 * @return javax.swing.JToggleButton	
	 */
	private JToggleButton getJToggleButton() {
		if (jToggleButton == null) {
			jToggleButton = new JToggleButton();
			jToggleButton.setBounds(new Rectangle(369, 452, 48, 28));
			//mp.setVisible(false);
			jToggleButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					
					if (jToggleButton.isSelected() && !mp.isVisible())
						mp.setVisible(true);
					else
						mp.setVisible(false);
				}
			});
			this.addComponentListener(new ComponentAdapter() {
				public void componentMoved(ComponentEvent arg0)
	            {
					Point location = getLocation();
	                mp.setLocation(location.x+getWidth()-500-150, location.y+getHeight()+10);
	    			
	            }
			});
			 
		}
		return jToggleButton;
	}

	/**
	 * This method initializes jPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 * @throws IOException 
	 */
	private JPanel getJPanel() throws IOException {
		if (jPanel == null) {
			GridBagConstraints gridBagConstraints = new GridBagConstraints();
			gridBagConstraints.fill = GridBagConstraints.BOTH;
			gridBagConstraints.gridy = 0;
			gridBagConstraints.weightx = 1.0;
			gridBagConstraints.weighty = 1.0;
			gridBagConstraints.gridx = 0;
			jPanel = new JPanel();
			jPanel.setLayout(new GridBagLayout());
			jPanel.setBounds(new Rectangle(56, 229, 700, 193));
			jPanel.add(getJScrollPane1(), gridBagConstraints);
		}
		return jPanel;
	}
}  //  @jve:decl-index=0:visual-constraint="10,10" 



/**
 * 
 * Class TextFilter
 * 
 * Read only .csnd files
 *
 */

class coSndFilter extends FileFilter {
    public boolean accept(File f) {
    if (f.isDirectory())
    return true;
    String s = f.getName();
    int i = s.lastIndexOf('.');

    if (i > 0 && i < s.length() - 1)
        if (s.substring(i + 1).toLowerCase().equals("csnd"))return true;
        return false;
    }

    public String getDescription() {
        return ".csnd";
    }
}
